﻿using System;
using System.Collections;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Diagnostics;
using System.Runtime.Serialization.Formatters.Binary;

namespace ContactsForm.Net
{
    /// <summary>
    /// Used for TCP notification of server data changes
    /// </summary>
    class client
    {

        private int _port;
        private IPAddress _ip;
        private DataArguments _data = new DataArguments();
        private TcpClient _client;
        private string _host;
        
        # region Properties
        public string DataArgs
        {
            get { return _data.DataArgs;}
            set { _data.DataArgs = value;}
        }

        /// <summary>
        /// Read Only property
        /// </summary>
        public string Data
        {
            get { return _data.Data; }
            set { _data.Data = value; }
        }
        /// <summary>
        /// Use this to write a string description of the data type so it'll be easier to figure out what the data is.
        /// </summary>
        public string DType
        {
            get { return _data.DType; }
            set { _data.DType = value; }
        }
    
        public int Port { get { return _port; } }
        public IPAddress IP { get { return _ip; } }
        
        # endregion 
        //need a read buffer size
        private Byte[] b = new Byte[256];
       // private string data = null;


        /// <summary>
        /// Creates and Starts a client service on the designated port and targets the specified host computer.
        /// </summary>
        /// <param name="port">Port to listen on.  Must between 1024 and 65535</param>
        /// <param name="host">The host computer to which you want to connect</param>
        public client(int port, string host)
        {
            if (port < 1024 || port > 65535)
            {
                throw new ArgumentOutOfRangeException("port", "Value must be be between 1024 and 65535.");
            }
            if (host == null)
            {
                throw new ArgumentNullException("Host can not be null");
            }
            try
            {
                _port = port;
                //_ip = ip;
                _host = host;
                // make client
                //IPEndPoint eip = new IPEndPoint(_ip, _port);
                _client = new TcpClient();
                
            }
            catch (SocketException ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.ErrorCode.ToString(), "socket error");
            }
        }
       

        public ManualResetEvent clientconnected = new ManualResetEvent(false);

        /// <summary>
        /// The Data to send to the connected clients
        /// </summary>
        /// <param name="data">Data to send.  Type is Tdata which is a custom data class</param>
        public void senddata()
        {
            clientconnected.Reset();
            _client.BeginConnect(_host, _port, new AsyncCallback(sendCallback), _client);
            clientconnected.WaitOne();
            _client.Close();
        }

        public void sendCallback(IAsyncResult a)
        {

            TcpClient client = (TcpClient)a.AsyncState;
            client.EndConnect(a);
            NetworkStream stream = client.GetStream();
            if (stream.CanWrite)
            {
                Byte[] send = Encoding.UTF8.GetBytes(_ip.ToString());
                stream.Write(send, 0, send.Length);
                
                byte[] bytedata;

                using (MemoryStream ms = new MemoryStream())
                {
                    BinaryFormatter bf = new BinaryFormatter();

                    try { bf.Serialize(ms, _data); }
                    catch { return; }

                    bytedata = ms.ToArray();
                }
                //stream.Write(BitConverter.GetBytes(bytedata.Length), 0, 4);
                stream.Write(bytedata, 0, bytedata.Length);
                stream.Close();
            }
            clientconnected.Set();
        }

        public Boolean writetcp()
        {
            return true;
        }

    }


}
